package suncertify.ui;

import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.Serializable;
import java.rmi.RemoteException;

import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import suncertify.controller.BookController;
import suncertify.db.RecordNotFoundException;
import suncertify.network.ServerHelper;
import suncertify.network.ServerInterface;
import suncertify.resources.App;

/**
 * The view presented to the user when they attempt to book a room.
 * This view gives the user the ability to enter a customer ID number
 * and book the room for the customer whose ID number matches.
 * @author Paul Wilhelm
 *
 */
public class BookGui implements Serializable, Subscriber{

	private static final long serialVersionUID = -3567871257328662311L;		//A UI to be used for deserialization verification
	private JFrame frame;				
	private GridBagConstraints constraint; 	
	private String name;			//The name of the hotel room
	private String location;		//The location of the hotel room
	private JFormattedTextField numberTxt;
	private BookController controller;		//The controller to handle all button clicks and actions
	private SearchGui searchGui;			//The searchGui object used in the application
	private JButton bookBtn;			
	private JButton cancelBtn;
	private JLabel alreadyBookedLabel;
	
	/**
	 * Constructor. Creates a new <code>BookGui</code> object to be shown at a later time
	 * @param name - The name of the room
	 * @param location - The location of the room
	 */
	public BookGui(String name, String location){
		searchGui = SearchGui.getInstance();
		controller = new BookController();
		constraint = new GridBagConstraints();
		this.name = name;
		this.location = location;
		frame = new JFrame();
	}
	
	/**
	 * Assembles all the components of the <code>BookGui</code> and then displays the
	 * components on the screen
	 */
	public void buildAndShowGui(){
		frame.setTitle("Book a Room");
		frame.setPreferredSize(new Dimension(500, 350));
		frame.setResizable(false);
		frame.setIconImage(App.icon);
		Container container = frame.getContentPane();
		container.add(buildMainPanel());
		if (App.isNetworked){								//If running in networked mode
			try {
				Subscriber remoteBookGui = ServerHelper.createRemoteSubscriber(this);
				WindowEventHandler weh = new WindowEventHandler(remoteBookGui);
				frame.addWindowListener(weh);
				App.localList.add(remoteBookGui);
				subscribeToChanges(remoteBookGui);
			} catch (RemoteException re){
				JOptionPane.showMessageDialog(null, "Error exporting the booking screen for use with the remote database");
				re.printStackTrace();
			}
		}
		frame.pack();
		frame.setVisible(true);
	}
	
	//Private, not a requirement to document
	private JPanel buildMainPanel(){
		JPanel mainPanel = new JPanel();
		mainPanel.setLayout(new GridBagLayout());
		
		//constraints for the description label 
		constraint.weightx = 1;
		constraint.weighty = 1;
		constraint.insets = new Insets(20, 20, 20, 20);
		constraint.gridy = 0;
		mainPanel.add(buildDescriptionLabel(), constraint);
		
		constraint.gridy = 1;
		mainPanel.add(buildAlreadyBookedLabel(), constraint);
		
		//constraints for the info label
		constraint.gridy = 2;
		mainPanel.add(buildInfoLabel(), constraint);
		
		//constraints for the customer number form
		constraint.gridy = 3;
		mainPanel.add(buildForm(), constraint);
				
		return mainPanel;
	}
	
	//Private, not a requirement to document
	private JLabel buildDescriptionLabel(){
		JLabel descriptonLabel = new JLabel("<HTML>Please enter the 8 digit customer number to book this room.</HTML>");
		return descriptonLabel;
	}
	
	//Private, not a requirement to document
	private JLabel buildAlreadyBookedLabel(){
		alreadyBookedLabel = new JLabel("<HTML><font color = 'red'>This room has been booked</HTML>");
		alreadyBookedLabel.setVisible(false);
		return alreadyBookedLabel;
	}
	
	//Private, not a requirement to document
	private JLabel buildInfoLabel(){
		JLabel infoLabel = new JLabel("<HTML><h2><font color ='blue'>Name: " + name + "<br>" + "Location: " + location + "</h2></HTML>");
		return infoLabel;
	}
	
	//Private, not a requirement to document
	private JPanel buildForm(){
		JPanel panel = new JPanel(new GridBagLayout());
		GridBagConstraints formConstraint = new GridBagConstraints();
		JLabel numberLbl = new JLabel("Customer Number: ");
		numberTxt = new JFormattedTextField();
		numberTxt.setColumns(20);
		cancelBtn = new JButton("Cancel");
		bookBtn = new JButton("Book");
		bookBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				try {
					if (numberTxt.getText().length() == 8){			//Verifies only 8 character are entered
						controller.bookBtnClick(numberTxt.getText(), name, location);
						searchGui.getResultsTable().setModel(new ResultsTableModel());
						searchGui.getResultsTable().updateUI();
						bookBtn.setEnabled(false);
						numberTxt.setEnabled(false);
						cancelBtn.setText("Close");
						if (App.isAlone){			//If running in alone mode
							bookBtn.setEnabled(false);
							numberTxt.setEnabled(false);
							cancelBtn.setText("Close");
							alreadyBookedLabel.setVisible(true);
						}
					}
					else {					//If more or less than 8 characters are entered
						JOptionPane.showMessageDialog(null, "The customer number must be 8 digits");
					}
				} catch (RecordNotFoundException e) {
					JOptionPane.showMessageDialog(null, e.getMessage(), "Record Not Found", JOptionPane.ERROR_MESSAGE);
				} catch (IOException e) {
					e.printStackTrace();
				} catch (NumberFormatException nfe){		//Verifies that all the characters entered are number
					JOptionPane.showMessageDialog(null, "The customer number must consist of only integers");
				}
			}
		});
		cancelBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				frame.dispose();
			}
		});
		
		//constraints for the number label
		formConstraint.gridy = 0;
		formConstraint.gridx = 0;
		panel.add(numberLbl, formConstraint);
		
		//constraints for the number field
		formConstraint.gridy = 0;
		formConstraint.gridx = 1;
		panel.add(numberTxt, formConstraint);
		
		//constraints for the book button
		formConstraint.gridy = 1;
		formConstraint.gridx = 0;
		formConstraint.insets.top = 5;
		formConstraint.gridwidth = 2;
		panel.add(bookBtn, formConstraint);
		
		//constraints for cancel button
		formConstraint.gridy = 1;
		formConstraint.gridx = 1;
		formConstraint.insets.left = 30;
		panel.add(cancelBtn, formConstraint);
		
		return panel;
	}

	/**
	 * {@inheritDoc}
	 */
	public void subscribeToChanges(Subscriber s) {
		try {
			ServerInterface data = ServerHelper.getRemoteDatabase();
			data.subscribe(s);
		} catch (RemoteException re){
			JOptionPane.showMessageDialog(null, "Unable to subscribe the view to data changes");
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void update(String requestorName, String requestorLocation) throws RemoteException {
		if (this.name.equals(requestorName) && this.location.equals(requestorLocation)){
			bookBtn.setEnabled(false);
			numberTxt.setEnabled(false);
			cancelBtn.setText("Close");
			alreadyBookedLabel.setVisible(true);
		}
	}
	
	/**
	 * Gets the main <code>JFrame</code> for the current view
	 * @return The frame for the view
	 */
	public JFrame getFrame(){
		return frame;
	}
	
	/**
	 * {@inheritDoc}
	 */
	public String getName(){
		return name;
	}
	
	/**
	 * {@inheritDoc}
	 */
	public String getLocation(){
		return location;
	}
	
	/**
	 * {@inheritDoc}
	 */
	public String getTitle(){
		return frame.getTitle();
	}

}
